package uk.co.hs.service.admin;

import java.util.ArrayList;
import java.util.List;

import javax.annotation.Resource;

import org.joda.time.DateTime;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.hibernate3.HibernateOptimisticLockingFailureException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import uk.co.hs.dao.web.admin.WebRoleDao;
import uk.co.hs.dao.web.admin.WebRoleUrlDao;
import uk.co.hs.dao.web.admin.WebUrlDao;
import uk.co.hs.domain.web.WebRole;
import uk.co.hs.domain.web.WebRoleUrl;
import uk.co.hs.domain.web.WebUrl;
import uk.co.hs.exceptions.DataAccessExceptions;
import uk.co.hs.service.admin.interfaces.WebRoleServiceInterface;
import uk.co.hs.web.util.AdminListDTO;
import uk.co.hs.web.util.RoleUrlWeb;

/**
 * WebRoleServiceImpl.
 */
@Service("hs_webRoleService")
@Transactional(value="hs_transactionManager")
public class WebRoleService implements WebRoleServiceInterface
{
  @Resource
  private WebRoleDao mWebRoleDao;

  @Resource
  private WebRoleUrlDao mWebRoleUrlDao;

  @Resource
  private WebUrlDao mWebUrlDao;

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getWebRole(java.lang.Long)
   * {@inheritDoc}
   */
  public WebRole getWebRole(Long aPk)
  {
    return mWebRoleDao.getById(aPk);
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getWebRoleUrls(java.lang.Long)
   * {@inheritDoc}
   */
  public List<WebRoleUrl> getWebRoleUrls(Long aRolePk)
  {
    return mWebRoleUrlDao.getWebRoleUrls(aRolePk);
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getAllWebUrls()
   * {@inheritDoc}
   */
  public List<WebUrl> getAllWebUrls()
  {
    return mWebUrlDao.getAllSortedByDescription();
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #saveWebRole(uk.co.hs.domain.web.WebRole)
   * {@inheritDoc}
   */
  public String saveWebRole(WebRole aWebRole)
  {
    aWebRole.setLastUpdated(new DateTime());
    try
    {
      mWebRoleDao.makePersistent(aWebRole);
    }
    catch (DataIntegrityViolationException aException)
    {
      return DataAccessExceptions.DATA_INTEGRITY_VIOLATION;
    }
    catch (HibernateOptimisticLockingFailureException aException)
    {
      return DataAccessExceptions.ALREADY_UPDATED;
    }
    catch (DataAccessException aException)
    {
      return DataAccessExceptions.DATA_ACCESS_FAILURE;
    }
    return null;
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #saveWebRoleAndWebUrlLinks(uk.co.hs.domain.web.WebRole, java.util.List)
   * {@inheritDoc}
   */
  public String saveWebRoleAndWebUrlLinks(WebRole aWebRole,
  		                              			List<RoleUrlWeb> aRoleUrlWebs)
  {
    if (aWebRole.getPk() == null && getWebRole(aWebRole.getName()) != null)
    {
      return "errors.role.with.same.name.already.exists";
    }

    String errorMessage = saveWebRole(aWebRole);
    if (errorMessage != null)
    {
      return errorMessage;
    }

    WebRole savedRole = getWebRole(aWebRole.getName());
    WebRoleUrl currentRoleUrlToSave;

    if (aWebRole.getPk() == null) // Is new Role
    {
      for (RoleUrlWeb current : aRoleUrlWebs)
      {
        currentRoleUrlToSave = new WebRoleUrl(savedRole, current.getUrl(), current.getEditable());
        errorMessage = saveWebRoleUrl(currentRoleUrlToSave);
        if (errorMessage != null)
        {
          return errorMessage;
        }
      }
    }
    else // Is an existing Role
    {
      for (RoleUrlWeb current : aRoleUrlWebs)
      {
        currentRoleUrlToSave = new WebRoleUrl(savedRole, current.getUrl(), current.getEditable());
        WebRoleUrl foundRoleUrl = getWebRoleUrl(current.getUrl(), savedRole);
        if (foundRoleUrl != null)
        {
          delete(foundRoleUrl);
        }

        if (current.getAccess())
        {
          errorMessage = saveWebRoleUrl(currentRoleUrlToSave);
          if (errorMessage != null)
          {
            return errorMessage;
          }
        }
      }
    }
    return null;
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #saveWebRoleUrl(uk.co.hs.domain.web.WebRoleUrl)
   * {@inheritDoc}
   */
  public String saveWebRoleUrl(WebRoleUrl aWebRoleUrl)
  {
    aWebRoleUrl.setLastUpdated(new DateTime());
    try
    {
      mWebRoleUrlDao.makePersistent(aWebRoleUrl);
    }
    catch (DataIntegrityViolationException aException)
    {
      return DataAccessExceptions.DATA_INTEGRITY_VIOLATION;
    }
    catch (HibernateOptimisticLockingFailureException aException)
    {
      return DataAccessExceptions.ALREADY_UPDATED;
    }
    catch (DataAccessException aException)
    {
      return DataAccessExceptions.DATA_ACCESS_FAILURE;
    }
    return null;
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getWebRole(java.lang.String)
   * {@inheritDoc}
   */
  public WebRole getWebRole(String aName)
  {
    return mWebRoleDao.getWebRole(aName);
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getWebRoleUrl(java.lang.Long)
   * {@inheritDoc}
   */
  public WebRoleUrl getWebRoleUrl(Long aWebRoleUrlId)
  {
    return mWebRoleUrlDao.getById(aWebRoleUrlId);
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getWebRoleUrl(uk.co.hs.domain.web.WebUrl, uk.co.hs.domain.web.WebRole)
   * {@inheritDoc}
   */
  public WebRoleUrl getWebRoleUrl(WebUrl aUrl, WebRole aRole)
  {
    return mWebRoleUrlDao.getRoleUrl(aUrl, aRole);
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getAllWebRoles()
   * {@inheritDoc}
   */
  public List<WebRole> getAllWebRoles()
  {
    return mWebRoleDao.getAll();
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getAllSortedRecords()
   * {@inheritDoc}
   */
  public List<AdminListDTO> getAllSortedRecords()
  {
    List<AdminListDTO> listItems = new ArrayList<AdminListDTO>();
    List<Object> currentObjectList;
    WebRole curerntRole;
    WebRole[] roles = getWebRoles();
    int roleCount = roles.length;
    for (int index = 0; index < roleCount; index++)
    {
      curerntRole = roles[index];
      currentObjectList = new ArrayList<Object>();
      currentObjectList.add(curerntRole.getName());

      List<Object> list = new ArrayList<Object>();
      list.add(curerntRole.getPk());

      listItems.add(new AdminListDTO(list, currentObjectList));
    }
    return listItems;
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #getWebRoles()
   * {@inheritDoc}
   */
  public WebRole[] getWebRoles()
  {
    List<WebRole> roleList = mWebRoleDao.getAll();
    WebRole[] roles = new WebRole[roleList.size()];
    for (int i = 0; i < roleList.size(); i++)
    {
      roles[i] = roleList.get(i);
    }
    return roles;
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #delete(uk.co.hs.domain.web.WebRole)
   * {@inheritDoc}
   */
  public void delete(WebRole aWebRole)
  {
    mWebRoleDao.makeTransient(aWebRole);
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #deleteWebRole(java.lang.Long)
   * {@inheritDoc}
   */
  public String deleteWebRole(Long aWebRoleId)
  {
    try
    {
      List<WebRoleUrl> foundListOfRoleUrls = getWebRoleUrls(aWebRoleId);
      delete(foundListOfRoleUrls);

      WebRole foundRole = getWebRole(aWebRoleId);
      if (foundRole != null)
      {
        delete(foundRole);
      }
    }
    catch (DataIntegrityViolationException aException)
    {
      return DataAccessExceptions.DATA_INTEGRITY_VIOLATION;
    }
    catch (HibernateOptimisticLockingFailureException aException)
    {
      return DataAccessExceptions.ALREADY_UPDATED;
    }
    catch (DataAccessException aException)
    {
      return DataAccessExceptions.DATA_ACCESS_FAILURE;
    }
    return null;
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #delete(java.util.List)
   * {@inheritDoc}
   */
  public void delete(List<WebRoleUrl> aListOfWebRoleUrls)
  {
    for (WebRoleUrl each : aListOfWebRoleUrls)
    {
      mWebRoleUrlDao.makeTransient(each);
    }
  }

  /**
   * @see uk.co.hs.service.admin.interfaces.WebRoleServiceInterface
   * #delete(uk.co.hs.domain.web.WebRoleUrl)
   * {@inheritDoc}
   */
  public void delete(WebRoleUrl aWebRoleUrl)
  {
    mWebRoleUrlDao.makeTransient(aWebRoleUrl);
  }
}
